﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Data;

namespace PlanningGIS.Util.IO
{
    /// <summary>
    /// 文件操作类
    /// </summary>
    public class FileHelper
    {
        #region 文件读写
        /// <summary>
        /// 读取文件
        /// </summary>
        /// <param name="fullname">要读取的文件全路径</param>
        /// <returns>文件的内容</returns>
        public static string ReadFile(string fullname)
        {
            return ReadFile(fullname, System.Text.Encoding.Default);
        }
        
        /// <summary>
        /// 读取文件
        /// </summary>
        /// <param name="fullname">要读取的文件全路径</param>
        /// <param name="encoding">文件编码</param>
        /// <returns>文件的内容</returns>
        public static string ReadFile(string fullname,System.Text.Encoding encoding)
        {
            if (string.IsNullOrEmpty(fullname) || !File.Exists(fullname))
                throw new Exception("文件【" + fullname + "】不存在，文件路径空");
            StreamReader reader = null;
            try
            {
                reader = new StreamReader(fullname, encoding);
                string value = "";
                string tmp = "";
                while ((tmp = reader.ReadLine()) != null)
                {
                    value += tmp.Trim() + "\r";
                }
                return value;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (reader != null)
                    reader.Close();
                reader = null;
            }
        }
        
        /// <summary>
        /// 将内容写入到文件中
        /// </summary>
        /// <param name="fullname">文件全路径</param>
        /// <param name="value">要写入的内容</param>
        public static void WriteFile(string fullname, string value)
        {
            StreamWriter sw = null;
            try
            {
                if (File.Exists(fullname))
                    sw = File.AppendText(fullname);
                else
                    sw = File.CreateText(fullname);
                sw.WriteLine(value);
                sw.Flush();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (sw != null)
                    sw.Close();
                sw = null;
            }
        }
        
        /// <summary>
        /// 将内容写入到文件中
        /// </summary>
        /// <param name="fullname">文件全路径</param>
        /// <param name="value">要写入的内容</param>
        /// <param name="encoding">文件编码</param>
        public static void WriteFile(string fullname, string value, System.Text.Encoding encoding)
        {
            FileStream fs = null;
            StreamWriter sw = null;
            try
            {
                if (File.Exists(fullname))
                    fs = new FileStream(fullname, FileMode.Create);
                else
                    fs = new FileStream(fullname, FileMode.Append);
                sw = new StreamWriter(fs, encoding); 
                sw.WriteLine(value);
                sw.Flush();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (sw != null)
                    sw.Close();
                if (fs != null)
                    fs.Close();
                sw = null;
                fs = null;
            }
        }

        /// <summary>
        /// 将二进制流写入到文件中
        /// </summary>
        /// <param name="fullname">要写入的文件</param>
        /// <param name="data">要写入的数据</param>
        public static void WriteFile(string fullname, byte[] data)
        {
            FileStream fs = null;
            BinaryWriter sr = null;
            try
            {
                fs = new FileStream(fullname, FileMode.OpenOrCreate);
                sr = new BinaryWriter(fs);
                sr.Write(data, 0, data.Length);
            }
            catch(Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (sr != null)
                    sr.Close();
                sr = null;
                if (fs != null)
                    fs.Close();
                fs = null;
            }
        }
        
        /// <summary>
        /// 文件转成内存流。
        /// </summary>
        /// <param name="fileName">文件名称。</param>
        /// <returns>转换得到的内存流。</returns>
        public static MemoryStream ReadMemoryStream(string fileName)
        {
            using (System.IO.FileStream fs = new System.IO.FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                byte[] bytes = new byte[fs.Length];
                fs.Read(bytes, 0, bytes.Length);
                return new MemoryStream(bytes);
            }
        }

        /// <summary>
        /// 读取文件到byte数组
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static byte[] ReadByte(string fileName)
        {
            using (System.IO.FileStream fs = new System.IO.FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                byte[] bytes = new byte[fs.Length];
                fs.Read(bytes, 0, bytes.Length);
                return bytes;
            }
        }

        #region ini文件读写
        /// <summary>
        /// API写入ini文件
        /// </summary>
        /// <param name="section">段落</param>
        /// <param name="key">键值</param>
        /// <param name="val">要写入的值</param>
        /// <param name="filePath">文件路径</param>
        /// <returns></returns>
        [DllImport("kernel32")]
        public static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
        
        /// <summary>
        /// API读取ini文件
        /// </summary>
        /// <param name="section">段落</param>
        /// <param name="key">键值</param>
        /// <param name="def">默认值</param>
        /// <param name="retVal"></param>
        /// <param name="size"></param>
        /// <param name="filePath">文件路径</param>
        /// <returns></returns>
        [DllImport("kernel32")]
        public static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);

        /// <summary>
        /// 写INI文件 
        /// </summary>
        /// <param name="section">段落</param>
        /// <param name="key">键值</param>
        /// <param name="value">要写入的值</param>
        /// <param name="inipath">文件路径</param>
        public static long WriteIniValue(string section, string key, string value, string inipath)
        {
            return WritePrivateProfileString(section, key, value, inipath);
        }

        /// <summary>
        /// 读取INI文件指定 
        /// </summary>
        /// <param name="section">段落</param>
        /// <param name="key">键值</param>
        /// <param name="defaultValue">默认值</param>
        /// <param name="inipath">文件路径</param>
        /// <returns></returns>
        public static string ReadIniValue(string section, string key, string defaultValue, string inipath)
        {
            StringBuilder temp = new StringBuilder(255);
            int i = GetPrivateProfileString(section, key, defaultValue, temp, 255, inipath);
            return temp.ToString();
        }

        #endregion
        
        #endregion
        
        /// <summary>
        /// 获取文件的编码类型
        /// </summary>
        /// <param name="filename">文件名称</param>
        /// <returns></returns>
        public static System.Text.Encoding GetFileEncodeType(string filename)
        {
            System.IO.FileStream fs = new System.IO.FileStream(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read);
            System.IO.BinaryReader br = new System.IO.BinaryReader(fs);
            Byte[] buffer = br.ReadBytes(2);
            if (buffer[0] >= 0xEF)
            {
                if (buffer[0] == 0xEF && buffer[1] == 0xBB)
                {
                    return System.Text.Encoding.UTF8;
                }
                else if (buffer[0] == 0xFE && buffer[1] == 0xFF)
                {
                    return System.Text.Encoding.BigEndianUnicode;
                }
                else if (buffer[0] == 0xFF && buffer[1] == 0xFE)
                {
                    return System.Text.Encoding.Unicode;
                }
                else
                {
                    return System.Text.Encoding.Default;
                }
            }
            else
            {
                return System.Text.Encoding.Default;
            }
        }

        #region 获取文件图标
        /// <summary>
        /// 
        /// </summary>
        /// <param name="pszPath"></param>
        /// <param name="dwFileAttributes"></param>
        /// <param name="psfi"></param>
        /// <param name="cbFileInfo"></param>
        /// <param name="uFlags"></param>
        /// <returns></returns>
        [DllImport("Shell32.dll")]
        static extern int SHGetFileInfo(string pszPath, uint dwFileAttributes, ref   SHFILEINFO psfi, uint cbFileInfo, uint uFlags);
        
        /// <summary>
        /// 文件信息
        /// </summary>
        struct SHFILEINFO
        {
            /// <summary>
            /// 图标句柄
            /// </summary>
            public IntPtr hIcon;
            /// <summary>
            /// 文件图标
            /// </summary>
            public int iIcon;
            /// <summary>
            /// 属性
            /// </summary>
            public uint dwAttributes;
            /// <summary>
            /// 显示名称
            /// </summary>
            public char szDisplayName;
            /// <summary>
            /// 类型名称
            /// </summary>
            public char szTypeName;
        }
        
        /// <summary>
        /// 从文件扩展名得到文件关联图标
        /// </summary>
        /// <param name="fileName">文件名或文件扩展名</param>
        /// <param name="smallIcon">是否是获取小图标，否则是大图标</param>
        /// <returns>图标</returns>
        public static Icon GetFileIcon(string fileName, bool smallIcon)
        {
            SHFILEINFO fi = new SHFILEINFO();
            Icon ic = null;
            //SHGFI_ICON + SHGFI_USEFILEATTRIBUTES + SmallIcon   
            int iTotal = (int)SHGetFileInfo(fileName, 100, ref fi, 0, (uint)(smallIcon ? 273 : 272));
            if (iTotal > 0)
            {
                ic = Icon.FromHandle(fi.hIcon);
            }
            return ic;
        }
        #endregion


        /// <summary>
        /// 获取文件大小
        /// </summary>
        /// <param name="fullFileName">文件路径</param>
        /// <returns>文件字节长度</returns>
        public static long GetFileSize(string fullFileName)
        {
            long size = 0;
            if (System.IO.File.Exists(fullFileName))
                size = new FileInfo(fullFileName).Length;
            return size;
        }

        /// <summary>
        /// 获取文件大小(KB)
        /// </summary>
        /// <param name="fullFileName"></param>
        /// <returns></returns>
        public static int GetFileSize_KB(string fullFileName)
        {
            long size = GetFileSize(fullFileName);
            return (int)(size / 1024);
        }

        /// <summary>
        /// 将CSV文件的数据读取到DataTable中
        /// </summary>
        /// <param name="filePath">CSV文件路径</param>
        /// <param name="fristRowHeader">第一行是否为列头</param>
        /// <returns></returns>
        public static DataTable OpenCSV(string filePath, bool fristRowHeader)
        {
            DataTable dt = new DataTable();
            System.IO.FileStream fs;
            try
            {
                fs = new System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
            }
            catch
            {
                throw new Exception("打开文件失败，可能是文件被其它程序锁定！");
            }
            StreamReader sr = new StreamReader(fs,Encoding.Default);
            string strLine = "";
            string[] aryLine = null;
            string[] tableHead = null;
            int columnCount = 0;
            bool IsFirstRow = true;
            while ((strLine = sr.ReadLine()) != null)
            {
                if (IsFirstRow == true)
                {
                    tableHead = strLine.Split(',');
                    IsFirstRow = false;
                    columnCount = tableHead.Length;
                    //创建列
                    for (int i = 0; i < columnCount; i++)
                    {
                        DataColumn dc;
                        if (fristRowHeader)
                        {
                            tableHead[i] = tableHead[i].Replace("\"", "");
                            dc = new DataColumn(tableHead[i]);
                        }
                        else
                        {
                            dc = new DataColumn();
                        }
                        dt.Columns.Add(dc);
                    }
                }
                if (IsFirstRow && fristRowHeader) continue;
                aryLine = strLine.Split(',');
                DataRow dr = dt.NewRow();
                for (int j = 0; j < columnCount; j++)
                {
                    dr[j] = aryLine[j].Replace("\"", "");
                }
                dt.Rows.Add(dr);
            }
            sr.Close();
            fs.Close();
            return dt;
        }

    }
}
